import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.List;


public class Audio {
	final static Charset ENCODING = StandardCharsets.ISO_8859_1;
	static final String HTML_FILE = "..\\index.html";
	static final String AUDIO_PATH="..\\audio\\";
	static File[] files;
	
	public static void main(String[] args) {
		try {
			
			// 1 - Remove mp3 wrap audio file
			cleanUp();
			
			// 2 - Get list of captions and convert them into mp3
			files = getAudioFiles();
			
			if (Util.isNullObject(files)){
				System.out.println("Can not get Audio files");
				System.exit(0);
			}
			
			for (File file : files) {
				String txt = file.getCanonicalPath();
				String wav = txt.replace(".txt", ".wav");
				String mp3 = txt.replace(".txt", ".mp3");
				
				txt2mp3(txt,wav,mp3);
			}
			
			// 3 - Write CuePoints to file
			int[] cuePoints = generateCuePoints();
			
			//4 Write Cue Points to Index HTML file
			writeCuePointsToIndexHTML(cuePoints);
			
			// 5 - Wrap all mp3 into one audio file
			mp3wrap();
			
			// 6 - Delete mp3 files
			if(args.length >= 1 && args[0].equals("nodel")){
				
				// Retain mp3 file for each slide
			}else {
				deleteMp3Files(files);
			}
			
			
		}catch(IOException ex){
			System.out.println(ex.toString());
		}
	}
	
	private static File[] getAudioFiles(){
		System.out.println("Getting Audio files...");
		File f = new File(AUDIO_PATH); // Captions directory
		System.out.println("Audio path -> " + f.getAbsolutePath());
		
         FilenameFilter audioFilter = new FilenameFilter() {
			public boolean accept(File dir, String name) {
				 String regEx = "audio-?\\d?\\d?\\.txt";
				 return (name.matches(regEx));
			}
 		};
 		
 		File[] files = f.listFiles(audioFilter);
 		
 		return files;
	}
	
	private static void txt2mp3(String txt, String wav, String mp3){
		
		try{
			
			// TODO find Empty file and add default silence of 1 second
			
			//System.out.println("Starting Balabolka...");
			String command1 = "bb -p 0 -s 0 -v 100 -n Brian -e 300 -a 500 --silence-begin 400 --silence-end 400 -f " +
				txt + " -w " + wav;
			
			Process process1 = Runtime.getRuntime().exec(command1);
			print("Generating wav file -> " + wav.substring(wav.length()-11, wav.length()));
			printProcessOutput(process1);
			process1.waitFor();
			
			String command2 = "lame -h --silent " + wav + " " +  mp3;
			Process process2 = Runtime.getRuntime().exec(command2);
			printProcessOutput(process2);
			print("Converting wav to mp3 file ->");
			process2.waitFor();
			
			print("Deleting wav file");
			new File(wav).delete();
			
		}catch(IOException ex){
			System.out.println(ex);
		}catch(InterruptedException ex){
			System.out.println(ex);
		}
		
	}
	
	private static int[] generateCuePoints(){
		int results[] = null;
		print("Generating Cue Points");
		BufferedReader b = null;
		StringBuffer t = null;
		
		try{				    
			String command = "mp3info -p %S, " + AUDIO_PATH + "*.mp3";
			Process process = Runtime.getRuntime().exec(command);
			BufferedReader in = new BufferedReader(  
                    new InputStreamReader(process.getInputStream()));
			
			String line = in.readLine();
			String delims = "[,]";
			String[] tokens = line.split(delims);
			
			t = new StringBuffer();
			
			t.append(tokens.length + " tokens\n");
			t.append("tokens: ");		
			
			for (int i=0; i < tokens.length - 1; i++){
				t.append(tokens[i] + ",");
			}
			
			t.append(tokens[tokens.length -1] + "\n");		
			
			int values[] = new int[tokens.length];
			
			for (int i=0; i < tokens.length; i++){
				values[i]= Integer.parseInt(tokens[i]);
			}
			
			results = new int[tokens.length];
			results[0] = values[0];
			
			int sum = values[0];
			
			for (int i=1; i < tokens.length; i++){
				sum = sum + values[i];
				results[i] = sum;			
			}
				
			t.append("cue Points :");
			
			for (int i=0; i < results.length - 1; i ++){
				t.append(results[i] + ",");			
			}
			t.append(results[results.length - 1] + "\n");
			
			System.out.print(t.toString());
			
		}catch(FileNotFoundException ex){
			System.out.println(ex);			
		}catch(IOException ex){
			System.out.println(ex);
		}finally {
			try {
				if (b != null)b.close();
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		
		/*print("Creating ..\\audio\\CuePoints.txt");
		try (BufferedWriter writer = Files.newBufferedWriter(Paths.get("..\\audio\\CuePoints.txt"),
				 Charset.forName("US-ASCII"), StandardOpenOption.CREATE)) {
	                
			writer.write(t.toString(), 0, t.toString().length());
	        
		} catch (IOException x) {
			System.out.println("Error Writing file" + x.toString());
		}*/
		
		return results;

	}
	
	static void writeCuePointsToIndexHTML(int[] cuePoints){
		print("Writing Cue Points to Index file");
		if (cuePoints.length < 1) return ;
		
		try{
			File file = new File(HTML_FILE);
			List <String> list = Files.readAllLines(file.toPath(), ENCODING);
			//System.out.println("index file lines = " + list.size());
			
			String temp = "";
			int line = 1;
			
			for (String s : list) {
				if (line == 1){
					temp = temp + s;
				}else{
					temp = temp + "\n" + s;
				}
				line++;
			}
			
			System.out.println("Splitting file...");
			String split[] = null;
			
			split = temp.split("(var)(\\s+)(cuepoints)(\\s+)(=)(\\s+)(\\[)(.*)(\\])(;)");
			String cueString = "";
			
			for (int i: cuePoints){
				cueString = cueString + i + ",";
			}
			
			// remove the last ,
			cueString = cueString.substring(0,cueString.length()-1);
			
			print("Cue String = " + cueString);
			
			String newContents = split[0] + "var cuepoints = [" + cueString + "];" + split[1];
			
			BufferedWriter bw = null;
			bw = new BufferedWriter(new FileWriter(HTML_FILE));
			bw.write(newContents);
			bw.close();
			
		}catch(Exception ex){
			System.out.println(ex.toString());
		}
	}
	
	private static void mp3wrap(){
		
		// mp3wrap -v ..\\audio.mp3 ..\\audio\\audio*.mp3
		String command1 = "mp3wrap -v ..\\audio.mp3 " + AUDIO_PATH + "audio*.mp3";
		
		try{
			Process process = Runtime.getRuntime().exec(command1);
			//print("Wrapping mp3 files");
			printProcessOutput(process);
			process.waitFor();
		}catch(IOException ex){
			System.out.println(ex);
		}catch(InterruptedException ex){
			System.out.println(ex);
		}
	}
	
	private static void deleteMp3Files(File[] files){
		print("Deleting mp3 files");
		
		try{
			for (File file : files) {
				String txt = file.getCanonicalPath();
				String mp3 = txt.replace(".txt", ".mp3");
				new File(mp3).delete();
			}
		}catch(IOException ex){
			System.out.println(ex.toString());
		}
		
	}
	
	private static void cleanUp(){
		print("Cleaning up...");
		
		String mp3 = "..\\audio_MP3WRAP.mp3";
		//String cuePoints = "..\\audio\\CuePoints.txt";
		
		File mp3File = new File(mp3);
		
		if (!Util.isNullObject(mp3) && mp3File.delete()) {
			print(mp3 + " is deleted");
		}
		
		/*if (new File(cuePoints).delete()) {
			print(cuePoints + " is deleted");
		}*/
		
	}
	
	private static void print(String msg){
		System.out.println(msg);
	}
	
	private static void printProcessOutput(Process p){
		try (BufferedReader in = new BufferedReader(  
                new InputStreamReader(p.getInputStream()))){
			
			String line = null;  
            while ((line = in.readLine()) != null) {  
                System.out.println(line);  
            }  
		}catch (IOException e) {  
            e.printStackTrace();  
        }
	}

}
